<?php defined('BASEPATH') or exit('No direct script access allowed');

class EXT_Model extends CI_Model 
{

	public $list_select = null;
	public $list_where = null;
	public $list_ordering = null;
	public $list_direction = null;
	public $list_orderby = array();

	public $item_select = null;
	public $item_where = null;
	public $item_orderby = null;

	public $list_filter_fields = array();

	protected $_default_list_select = null;
	protected $_default_list_where = null;
	protected $_default_list_orderby = null;

	protected $_default_item_select = null;
	protected $_default_item_where = null;
	protected $_default_item_orderby = null;

	protected $_table = null;
	protected $_primary_key = 'id';
	protected $_blankItem = null;
	protected $_fields = array();
	protected $_total = 0;
	protected $_items = array();

	public function __construct() 
	{
		parent::__construct();
		$this->load->database();
		$this->_default_list_select = $this->list_select;
		$this->_default_list_where = $this->list_where;
		$this->_default_list_orderby = $this->list_orderby;

		$this->_default_item_select = $this->item_select;
		$this->_default_item_where = $this->item_where;
		$this->_default_item_orderby = $this->item_orderby;
	}
	public function init($options=null)
	{
	}
	public function getDb()
	{
		return $this->db;
	}
	public function getList($limit=0, $limit_start=0)
	{
		$data = array();

		if(!is_null($this->list_select))
		{
			$this->db->select($this->list_select);
			$this->list_select = $this->_default_list_select;
		}

		$this->db->from($this->_table);

		if(!is_null($this->list_where))
		{
			$this->db->where($this->list_where);
			$this->list_where = $this->_default_list_where;
		}
		if(!empty($this->list_filter_fields)
			&& in_array($this->list_ordering, $this->list_filter_fields)
			&& in_array(strtoupper($this->list_direction), array('ASC', 'DESC'))
		)
		{
			$tmp = array($this->list_ordering.' '.$this->list_direction);
			$this->list_orderby = array_merge($tmp, $this->list_orderby);
		}

		if($this->list_orderby)
		{
			$list_orderby = array_merge($this->list_orderby, $this->_default_list_orderby);
			$this->list_orderby = $this->_default_list_orderby;
			$list_orderby = array_unique(array_filter($list_orderby));
			foreach($list_orderby as $orderby)
			{
				$orderby = str_replace(array(' desc', ' asc'), array(' DESC', ' ASC'), $orderby);
				$this->db->order_by(trim($orderby));
				if(strtoupper($orderby) == 'RAND()')
				{
					break;
				}
				if(str_replace(array(' DESC', ' ASC'), '', $orderby) == $this->_primary_key)
				{
					break;
				}
			}
		}
		$tempdb = clone $this->db;
		$this->_total = $tempdb->count_all_results();

		if($limit)
		{
			$this->db->limit($limit, $limit_start);
		}
		$Q = $this->db->get();
		if ($Q->num_rows() > 0)
		{
			$data = $Q->result();
		}
		return $data;
	}
	public function getTotal()
	{
		return $this->_total;
	}
	public function getItem($pk=null)
	{
		if(isset($this->_items[$pk]))
		{
			return $this->_items[$pk];
		}

		if(!is_null($this->item_select))
		{
			$this->db->select($this->item_select);
			$this->item_select = $this->_default_item_select;
		}

		$this->db->from($this->_table);

		if(!is_null($this->item_where))
		{
			$this->db->where($this->item_where);
			$this->item_where = $this->_default_item_where;
		}

		if(!is_null($pk))
			$this->db->where('id', $pk);

		if(!is_null($this->item_orderby))
		{
			$this->db->order_by($this->item_orderby);
			$this->item_orderby = $this->_default_item_orderby;
		}
		$item = $this->db->get()->row();
		if($item)
		{
			$this->_items[$item->id] = $item;
		}
		return $item;
	}
	public function fields()
	{
		$this->_fields = $this->db->field_data($this->_table);
		return $this->_fields;
	}
	public function blankItem()
	{
		$this->_fields = $this->fields();
		if($this->_blankItem != null)
			return $this->_blankItem;

		$this->_blankItem = new stdClass();
		foreach($this->_fields as $field)
		{
			$this->_blankItem->{$field->name} = $field->default;
		}
		return $this->_blankItem;
	}
	public function save($data=null)
	{
		if(is_null($data))
			$data = $this->input->post();

		$this->bind($data);
		if(isset($data[$this->_primary_key]) && $data[$this->_primary_key]>0)
		{
		// UPDATE
			return $this->update($data);
		}
		// INSERT
		return $this->insert($data);
	}
	public function bind(& $data)
	{
		$fields = array_keys((array)$this->blankItem());
		foreach($data as $idx=>$val)
		{
			if(!in_array($idx, $fields))
				unset($data[$idx]);
		}
		return $data;
	}
	public function update($data)
	{
		$pk = $data[$this->_primary_key];
		$where = $this->_primary_key.' = '.$data[$this->_primary_key];
		unset($data[$this->_primary_key]);
		$this->db->trans_start();
		$this->db->update($this->_table, $data, $where);
		$this->db->trans_complete();
		if($this->db->trans_status() === false)
			return false;

		return $pk;
	}
	public function insert($data)
	{
		if(isset($data[$this->_primary_key]))
			unset($data[$this->_primary_key]);

		$this->db->trans_start();
		$this->db->insert($this->_table, $data);
		$this->db->trans_complete();
		if($this->db->trans_status() === false)
			return false;

		return $this->db->insert_id();
	}
	public function delete($pk, $where='')
	{
		$this->db->trans_start();
		if($pk)
		{
			$this->db->where($this->_primary_key, $pk);
		}
		if($where)
		{
			$this->db->where($where);
		}
		$this->db->delete($this->_table); 
		$this->db->trans_complete();
		if($this->db->trans_status() === false)
			return false;

		return $pk;
	}
	public function countAll()
	{
		return $this->db->count_all($this->_table);
	}
}


